package com.wentao.mall.api

import com.wentao.mall.dao.*
import com.wentao.mall.entity.ListConverter
import org.apache.commons.lang3.RandomStringUtils
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RestController
import java.time.LocalDate
import java.time.format.DateTimeFormatter
import javax.persistence.*

val DAY_MAX_POINTS = 1000
val SIGN_POINTS = 200

@RestController
class UserController(
    val userDao: UserDao,
    val merchantDao: MerchantDao,
    val orderDao: OrderDao,
    val pointsHistoryDao: PointsHistoryDao,
    val todayInfoDao: TodayInfoDao,
) {

    @GetMapping("/api/user/{openId}")
    fun userDetails(@PathVariable openId: String): Result {
        val user = userDao.findByOpenid(openId) ?: return Result.errorUserNotFound()
        val todayInfo = todayInfoDao.findByUserIdAndDate(user.id, LocalDate.now().toString())
            ?: TodayInfo(
                userId = user.id,
                date = LocalDate.now().toString(),
                pointsEarned = 0,
                stepsFromWx = 0
            )


        return Result.success(user.copy(todayInfo = todayInfo))
    }

    @PostMapping("/api/mock-user")
    fun mockUser(): Result {
        var user = User(
            openid = RandomStringUtils.randomAlphabetic(4),
            isVIP = true,
        )
        user = userDao.save(user)
        return Result.success(user)
    }

    /**
     * 签到
     */
    @PostMapping("/api/user/{openId}/sign")
    fun signToday(@PathVariable openId: String): Result {
        val user = userDao.findByOpenid(openId)
            ?: return Result.errorUserNotFound()
        val signNum = user.signDays
        val lastSignDateStr = user.lastSignDate
        val now = LocalDate.now()
        val nowStr = now.format(DateTimeFormatter.ISO_LOCAL_DATE)
        if (lastSignDateStr == null) {
            user.signDays = signNum + 1
            user.lastSignDate = nowStr
        } else {
            val lastSignDate = LocalDate.parse(lastSignDateStr, DateTimeFormatter.ISO_LOCAL_DATE)

            val period = lastSignDate.until(now).days
            when {
                period == 1 -> {
                    user.signDays = signNum + 1
                    user.lastSignDate = nowStr
                }
                period > 1 -> {
                    user.signDays = 1
                    user.lastSignDate = nowStr
                }
                else -> {
                    return Result.error("already signed")
                }
            }
        }
        user.points = user.points + SIGN_POINTS

        userDao.save(user)

        val todayInfo = todayInfoDao.findByUserIdAndDate(user.id, nowStr) ?: TodayInfo(
            userId = user.id,
            date = nowStr,
            pointsEarned = 0,
            stepsFromWx = 0
        )

        todayInfo.pointsEarned = todayInfo.pointsEarned + SIGN_POINTS
        todayInfoDao.save(todayInfo)


        return Result.success(object {
            val signDays: Int = user.signDays
            val pointsEarned: Int = todayInfo.pointsEarned
            val pointsLeft: Int = todayInfo.pointsLeft
        })

    }

    @GetMapping("/api/user/{openId}/orders")
    fun userMerchantOrder(@PathVariable openId: String, merchantId: Int?): Result {
        val user = userDao.findByOpenid(openId) ?: return Result.errorUserNotFound()

        val list = if (merchantId == null)
            orderDao.findByOpenId(openId)
        else
            orderDao.findByOpenIdAndMerchantId(openId, merchantId)


        return Result.success(list)
    }

    @GetMapping("/api/user/{openId}/pointsHistory")
    fun userPointsHistory(@PathVariable openId: String): Result {
        val list = pointsHistoryDao.findByOpenId(openId)
        return Result.success(list)
    }

}

@Entity
data class User(
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    val id: Int = -1,
    val openid: String? = null,
    val unionId: String? = null,

    val nickname: String? = null, //微信昵称
    val gender: Int? = null,
    val country: String? = null,
    val province: String? = null,
    val city: String? = null,
    val language: String? = null,
    val avatarUrl: String? = null, // 头像

    var signDays: Int = 0,
    var lastSignDate: String? = null,

    val phoneNumber: String? = null, // 手机号
    var points: Int = 0, // 积分

    @Convert(converter = ListConverter::class)
    val merchantLightUp: List<Int> = listOf(), // 商户点亮列表

    val merchantLightUpNum: Int = merchantLightUp.size, // 商户点亮数

    val babyGender: String? = null,
    val babyBithday: String? = null,
    @Convert(converter = ListConverter::class)
    val inviteList: List<String> = listOf(), // 邀请用户

    val isVIP: Boolean = false,

    @Transient
    val todayInfo: TodayInfo? = null,

    ) {

    val isSign: Boolean
        get() = lastSignDate?.let {
            LocalDate.now().toString().equals(it)
        } ?: false

}
